package cn.com.bluemoon.daps.system.controller.api;


import cn.com.bluemoon.daps.api.sys.RemoteSystemDatasourceService;
import cn.com.bluemoon.daps.common.annotation.FcApiFor;
import cn.com.bluemoon.daps.common.constant.ServiceNameConstants.DapsApiSystem;
import cn.com.bluemoon.daps.common.datascope.BmPermission;
import cn.com.bluemoon.daps.common.datascope.IgnorePermission;
import cn.com.bluemoon.daps.common.domain.BaseModel;
import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.common.enums.BmStatus;
import cn.com.bluemoon.daps.common.enums.DatabaseType;
import cn.com.bluemoon.daps.system.dto.DatasourceDto;
import cn.com.bluemoon.daps.system.dto.SystemDatasourceDto;
import cn.com.bluemoon.daps.system.entity.DapSystemDatasource;
import cn.com.bluemoon.daps.system.entity.DapSystemDatasourceEnvironment;
import cn.com.bluemoon.daps.system.entity.DapSystemInfo;
import cn.com.bluemoon.daps.system.entity.DapSystemSchema;
import cn.com.bluemoon.daps.system.service.DapSystemDatasourceEnvironmentService;
import cn.com.bluemoon.daps.system.service.DapSystemDatasourceService;
import cn.com.bluemoon.daps.system.service.DapSystemInfoService;
import cn.com.bluemoon.daps.system.service.DapSystemSchemaService;
import cn.com.bluemoon.daps.system.utils.ConnectUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Api(tags = {"FeignClient服务-数据源api接口"})
@RequestMapping(DapsApiSystem.API_DATASOURCE)
@IgnorePermission(name = "服务注册-数据源")
@RestController
@Slf4j
public class DapDatasourceApi implements RemoteSystemDatasourceService {

    @Resource
    DapSystemDatasourceService dapSystemDatasourceService;

    @Resource
    DapSystemDatasourceEnvironmentService dapSystemDatasourceEnvironmentService;

    @Resource
    DapSystemInfoService dapSystemInfoService;

    @Resource
    DapSystemSchemaService dapSystemSchemaService;
    /**
     * 根据数据源id查询数据源信息
     *
     * @param id
     * @return
     */
    @GetMapping("/datasource/{id}")
    public ResultBean<DapSystemDatasource> getDatasource(@PathVariable("id") String id) {

        DapSystemDatasource datasource = dapSystemDatasourceService.getBaseMapper()
                .selectById(id);
        return ResultBean.ok(datasource);
    }

    @GetMapping("/get")
    public DapSystemDatasource getById(@RequestParam("id") String id) {
        return dapSystemDatasourceService.getCacheOneById(id).orElse(null);
    }

    @PostMapping("/datasource/list")
    @FcApiFor(team = "数据资产团队")
    public ResultBean<List<DatasourceDto>> getDatasourceList() {

        // 查询所有的数据源
        List<DapSystemDatasource> dapSystemDatasourceList = dapSystemDatasourceService.getBaseMapper().selectList(new LambdaQueryWrapper<DapSystemDatasource>()
                .eq(DapSystemDatasource::getBmStatus, BmStatus.ON.getCode()));
        // 获得id列表
        List<String> ids = dapSystemDatasourceList.stream().map(DapSystemDatasource::getId).collect(Collectors.toList());
        // 查询数据源环境信息
        if(!ids.isEmpty()){
            List<DapSystemDatasourceEnvironment> dapSystemDatasourceEnvironments = dapSystemDatasourceEnvironmentService.getBaseMapper()
                    .selectList(new LambdaQueryWrapper<DapSystemDatasourceEnvironment>().in(DapSystemDatasourceEnvironment::getDatasourceId, ids)
                            .eq(DapSystemDatasourceEnvironment::getBmStatus, BmStatus.ON.getCode()));
            List<DatasourceDto> list = new ArrayList();
            dapSystemDatasourceList.forEach(d -> {
                List<DapSystemDatasourceEnvironment> collect = dapSystemDatasourceEnvironments.stream()
                        .filter(e -> d.getId().equals(e.getDatasourceId())).collect(Collectors.toList());
                DatasourceDto datasourceDto = new DatasourceDto();
                datasourceDto.setDapSystemDatasource(d);
                datasourceDto.setList(collect);
                list.add(datasourceDto);
            });
            return ResultBean.ok(list);
        }
        return ResultBean.error("数据源信息不存在");
    }

    /**
     * 元数据调用
     * @param ids
     * @return
     */
    @PostMapping("")
    @FcApiFor(team = "数据资产团队")
    public ResultBean<List<DatasourceDto>> datasourceList(@RequestBody List<String> ids){

        if(ids.isEmpty()){
            return ResultBean.ok(null);
        }
        List<DatasourceDto> list = dapSystemDatasourceService.getDatasourceInfoList(ids);
        return ResultBean.ok(list);
    }


    @GetMapping("/get/source/info")
    public ResultBean<DatasourceDto> getDatasourceInfo(@RequestParam("id") String id) {
        return ResultBean.ok(dapSystemDatasourceService.getDatasourceInfo(id));
    }

    @GetMapping("exist/environment")
    public ResultBean<Boolean> isExistPreAndProEnvironment(@RequestParam("datasourceId") String datasourceId){

        List<DapSystemDatasourceEnvironment> dapSystemDatasourceEnvironments = dapSystemDatasourceEnvironmentService.getBaseMapper()
                .selectList(new LambdaQueryWrapper<DapSystemDatasourceEnvironment>().eq(DapSystemDatasourceEnvironment::getDatasourceId, datasourceId)
                .eq(DapSystemDatasourceEnvironment::getBmStatus, BmStatus.ON.getCode()).eq(DapSystemDatasourceEnvironment::getIsInfoResource, false)
                .in(DapSystemDatasourceEnvironment::getEnvironment, 3,4));
        if(dapSystemDatasourceEnvironments.size() == 2){
            return ResultBean.ok(true);
        }else if(dapSystemDatasourceEnvironments.isEmpty()){
            return ResultBean.error("模型绑定的数据源不存在预发布和生产环境");
        }else {
            List<Integer> collect = dapSystemDatasourceEnvironments.stream().map(DapSystemDatasourceEnvironment::getEnvironment).collect(Collectors.toList());
            return ResultBean.error(String.format("模型绑定的数据源不存在%s环境", collect.contains(3) ? "生产" : "预发布"));
        }
    }

    @PostMapping("sys/datasource")
    @FcApiFor(team = "数据资产团队")
    public ResultBean<List<SystemDatasourceDto>> getResourceBySystemId(@RequestBody List<String> systemIdList){

        if(systemIdList.isEmpty()){
            return ResultBean.error("入参不能为空");
        }
        // 批量查询系统信息
        List<DapSystemInfo> systemInfos = dapSystemInfoService.getBaseMapper().selectList(new LambdaQueryWrapper<DapSystemInfo>().in(DapSystemInfo::getId, systemIdList)
                .eq(DapSystemInfo::getBmStatus, BmStatus.ON.getCode()));
        // 获得系统列表
        List<String> collect = systemInfos.stream().map(DapSystemInfo::getId).collect(Collectors.toList());
        // 过滤掉不存在的系统id
        List<String> notExistId = systemIdList.stream().filter(i -> !collect.contains(i)).collect(Collectors.toList());
        if(!notExistId.isEmpty()){
            return ResultBean.error(String.format("系统id%s不存在", notExistId));
        }
        // 批量查询系统数据源的信息
        List<DapSystemDatasource> list = dapSystemDatasourceService.getBaseMapper().selectList(new LambdaQueryWrapper<DapSystemDatasource>()
                .in(DapSystemDatasource::getSystemInfoId, systemIdList).eq(DapSystemDatasource::getBmStatus, BmStatus.ON.getCode()));
        List<String> sysIds = list.stream().map(DapSystemDatasource::getSystemInfoId).collect(Collectors.toList());
        List<String> unBindISystemName = systemInfos.stream().filter(s -> !sysIds.contains(s.getId())).map(DapSystemInfo::getName).collect(Collectors.toList());
        if(!unBindISystemName.isEmpty()){
            return ResultBean.error(String.format("系统%s未绑定数据源", unBindISystemName));
        }
        List<String> datasourceIds = list.stream().map(DapSystemDatasource::getId).collect(Collectors.toList());
        // 查询数据源环境
        List<DatasourceDto> dtoList = dapSystemDatasourceService.getDatasourceInfoList(datasourceIds);
        // 组装数据
        List<SystemDatasourceDto> systemDatalist = Lists.newArrayList();
        dtoList.forEach(d -> {
            SystemDatasourceDto systemDatasourceDto = new SystemDatasourceDto();
            systemInfos.forEach(s -> {
                if(s.getId().equals(d.getDapSystemDatasource().getSystemInfoId())){
                   systemDatasourceDto.setDapSystemInfo(s);
                }
            });
            BeanUtils.copyProperties(d,systemDatasourceDto);
            systemDatalist.add(systemDatasourceDto);
        });
        return ResultBean.ok(systemDatalist);

    }

    @GetMapping("by/dbType")
    public ResultBean<List<DapSystemDatasource>> getDatasourceByDatabaseType(@RequestParam("databaseType") DatabaseType databaseType){

        LambdaQueryWrapper<DapSystemDatasource> eq = new LambdaQueryWrapper<DapSystemDatasource>().eq(DapSystemDatasource::getBmStatus, BmStatus.ON.getCode())
                .eq(DapSystemDatasource::getDatabaseType, databaseType);
        List<DapSystemDatasource> list = dapSystemDatasourceService.getBaseMapper().selectList(eq);
        return ResultBean.ok(list);
    }

    @GetMapping("schema/datasource")
    public ResultBean<Map<String, List<DapSystemDatasourceEnvironment>>> getSchemaDatasourceList(@RequestParam("schemaId") String schemaId){

        DapSystemSchema dapSystemSchema = dapSystemSchemaService.getBaseMapper().selectById(schemaId);
        if(dapSystemSchema == null){
            return ResultBean.error("schema不存在");
        }
        String datasourceIds = dapSystemSchema.getDatasourceIds();
        List<String> list = Arrays.asList(datasourceIds.split(","));
        // 查询数据源
        List<DapSystemDatasource> datasourceList = dapSystemDatasourceService.getBaseMapper().selectBatchIds(list);
        // 查询数据源环境
        LambdaQueryWrapper<DapSystemDatasourceEnvironment> eq = new LambdaQueryWrapper<DapSystemDatasourceEnvironment>()
                .eq(BaseModel::getBmStatus, BmStatus.ON.getCode())
                .eq(DapSystemDatasourceEnvironment::getIsInfoResource, false)
                .eq(DapSystemDatasourceEnvironment::getEnvironment, dapSystemSchema.getEnvironment())
                .in(DapSystemDatasourceEnvironment::getDatasourceId, list);
        List<DapSystemDatasourceEnvironment> environments = dapSystemDatasourceEnvironmentService.getBaseMapper().selectList(eq);
        Map<String, DatabaseType> map = datasourceList.stream().collect(Collectors.toMap(DapSystemDatasource::getId, DapSystemDatasource::getDatabaseType));
        List<DapSystemDatasourceEnvironment> collect = environments.stream().filter(e -> map.containsKey(e.getDatasourceId()))
                .peek(e -> {e.setPassword(e.decryptPassword());e.setDbType(map.get(e.getDatasourceId()));}).collect(Collectors.toList());
        Map<String, List<DapSystemDatasourceEnvironment>> schemaMap = new HashMap<>();
        schemaMap.put(dapSystemSchema.getSchemaName(), collect);
        return ResultBean.ok(schemaMap);
    }

    @GetMapping("schema/list")
    public ResultBean<List<DapSystemSchema>> getSchemaList(){

        LambdaQueryWrapper<DapSystemSchema> eq = new LambdaQueryWrapper<DapSystemSchema>().eq(DapSystemSchema::getBmStatus, BmStatus.ON.getCode());
        List<DapSystemSchema> dapSystemSchemas = dapSystemSchemaService.getBaseMapper().selectList(eq);
        return ResultBean.ok(dapSystemSchemas);

    }
}
